/**
 * @author Kristian Mandrup
 * @date June 10, 2009
 * @version 0.1
 * 
 * m3gen :: JSONObjParser
 * 
 * - Parses a JSON object to create a generic NodeObj with properties needed to create a tree node, fx a JsTree node
 * 
 * Usage 
 * -----
 * var my_jsonObj = {...}; // JSON obj
 * var my_JsonObjParser = new JsonObjParser(createOptions);
 * var my_nodeObjModel = my_JsonObjParser.execute(my_jsonObj, ruleSet);
 */

/**
 * JSONObjParser constructor
 * Sets up JSONObjParser for use
 * 
 * @param {Object} createOptions
 * 
 * createOptions:
 * - constructors
 * - globalExecState
 * 
 */
m3gen.JSONObjParser = function(createOptions) {
	if (arguments.length < 1 || m3gen.util.invalidOptions(createOptions))
		return;
	this.init(createOptions);
}

// inherit from Parser
m3gen.JSONObjParser.inherits(m3gen.Base);

/**
 * Initialize JSONObjParser 
 * @param {Object} createOptions
 * 
 * createOptions:
 * - createOptions
 * - globalExecState
 */
m3gen.JSONObjParser.prototype.init = function(createOptions){
	this.setClassName('JSONObjParser');		
		
	// call Parser superclass initializer 
	this.uber('init', createOptions);		
	// this.setGlobalExecState(createOptions.globalExecState);	
	this.clearGlobalExecState();
}


/**
 * Public
 * A JSONObjParser must always have an execute function
 * 
 * @param 	jsonObj
 * @param 	options
 * 
 * @return 	{NodeObj} 	nodeObj
 * 
 * options:
 * - isChild (to calculate depth)
 * - isReference (to avoid resolving children)
 * 
 */

/**
 * doExecute default empty wrapper
 * @param {Object} options
 */
m3gen.JSONObjParser.prototype.execute = function(options){
	return this.doExecute(options);
}

m3gen.JSONObjParser.prototype.doExecute = function (jsonObj, options) {	
	// is it a child reference we are parsing? 
	// if so, then we should avoid parsing children for this obj!
	var isReference = false;
	if (this.isValidObj(options))
		isReference = options.isReference || false;

	// get ruleSet Configuration	
	var ruleSetConfiguration = this.getRuleSetConfiguration();
	jsonObj = this.validObj(jsonObj);

	if (this.isValidRuleSetConfiguration(ruleSetConfiguration)) {

		// set active jsonObj (also sets active objType and ruleSet)
		var activeObj = this.setActiveObj(jsonObj);		
		// get active objType			
		var activeObjType = this.getActiveObjType();			
		// get active ruleSet

		var activeRuleSet = this.getActiveRuleSet();		
		// resolve content of jsonObj
		var resolvedContent = this.resolveJsonObjContent();

		if (this.isValidObj(resolvedContent)) {
			// create a nodeObj model from the resolved content
			var nodeObj = this.resolveNodeObj(resolvedContent, isReference);
			// and return it
			return nodeObj
		}
		else {
			console.log('Invalid resolvedContent!')
			this.handle(m3gen.msg.InvalidResolvedContent);
		}
	} else this.handle(m3gen.msg.InvalidRuleSetConfiguration)
}		

/**
 * Resolve a single nodeObj model
 * FLOW:
 * - try to build a nodeObj
 * - IF valid nodeObj
 *  	- get the ID
 *  	- instance or reference?
 *  	- update visited list
 *  	- IF not a reference node
 *  		- resolve children i
 *  		- put children on nodeObj
 * - return nodeObj
 * 
 * @param 	{Object} 	resolvedContent	
 * @param 	{Object} 	isReference		
 * 
 * @return 	{NodeObj} 	nodeObj
 */
m3gen.JSONObjParser.prototype.resolveNodeObj = function(resolvedContent, isReference){	
	// try to build a nodeObj
	var nodeObj = this.getNodeObjBuilderInstance().execute(resolvedContent);	
	if (this.isValidNodeObj(nodeObj)) {
		// get the ID
		var id = this.getIdFromNodeObj(nodeObj);
		
		// determine instance or reference 
		var nodeType = this.getNodeType(id);
		// update visited list accordingly
		this.addIdToVisitedListConditional(id);
		
		// if not a reference node, try to resolve children
		if (!(this.isReference(nodeType) || isReference)) {
			var nodeObjChildren = this.getChildrenParserInstance().execute();
			// put children on nodeObj if there are any
			this.putChildrenOnNodeObj(nodeObj, nodeObjChildren);
		}
		// return the nodeObj
		return nodeObj;
	}
	else {
		console.log('invalid node');
	}
}
	
/**
 * TODO: Support resolving icon/title when 'language option' if OFF
 * 
 * Resolve JsonObj to get content needed
 * 
 * @return 	{Object} resolvedContent - resolved content of a jsonObj used to build a nodeObj
 */
m3gen.JSONObjParser.prototype.resolveJsonObjContent = function() {					
	var resolvedContent = this.getResolvedContentBuilderInstance().buildFromJson();	
	return resolvedContent;
}


